﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace FirstFloor.Documents.Pdf.Fonts
{
    /// <summary>
    /// Represents a font encoding.
    /// </summary>
    internal class FontEncoding
    {
        private CharacterToGlyphNameMap cmap;
        private Dictionary<char, string> differences;

        /// <summary>
        /// Initializes a new instance of the <see cref="FontEncoding"/> class.
        /// </summary>
        /// <param name="fontDictionary">The font dictionary.</param>
        /// <param name="flags">The flags.</param>
        public FontEncoding(DictionaryObject fontDictionary, FontFlags flags)
        {
            var encoding = fontDictionary.Get<object>("Encoding", null);
            var encodingName = encoding as string;
            if (encodingName == null) {
                var encodingDict = encoding as DictionaryObject;
                if (encodingDict != null) {
                    encodingName = encodingDict.Get<string>("BaseEncoding", null);

                    this.differences = GetDifferences(encodingDict.Get<ArrayObject>("Differences", null));

                    // TODO: load cmap from somewhere
                    this.cmap = new CharacterToGlyphNameMap();
                }
                else {
                    if ((flags & FontFlags.Nonsymbolic) != 0) {     // non-symbolic
                        this.cmap = CharacterToGlyphNameMap.StandardEncoding;
                    }
                }
            }

            if (encodingName == "MacRomanEncoding") {
                this.cmap = CharacterToGlyphNameMap.MacRomanEncoding;
            }
            else if (encodingName == "MacExpertEncoding") {
                //this.cmap = CharacterToGlyphNameMap.MacOSRomanEncoding;
            }
            else if (encodingName == "WinAnsiEncoding") {
                this.cmap = CharacterToGlyphNameMap.WinAnsiEncoding;
            }
        }

        private Dictionary<char, string> GetDifferences(ArrayObject differences)
        {
            Dictionary<char, string> result = null;

            if (differences != null) {
                result = new Dictionary<char, string>();

                char currentCode = char.MinValue;
                for (int i = 0; i < differences.Count; i++) {
                    var value = differences[i];
                    var code = value as double?;
                    if (code.HasValue) {
                        currentCode = (char)code.Value;
                    }
                    else {
                        var name = value as string;
                        if (name != null) {
                            result[currentCode++] = name;
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Gets the glyph name of given character.
        /// </summary>
        /// <param name="c">The c.</param>
        /// <returns></returns>
        public string GetGlyphName(char c)
        {
            string name;

            if (this.differences != null && this.differences.TryGetValue(c, out name)) {
                return name;
            }

            if (this.cmap != null && this.cmap.TryGetName(c, out name)) {
                return name;
            }

            return null;        // could not find name
        }
    }
}
